home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
IRIX Installation Tools & Overlays 2001 November
/
SGI IRIX Installation Tools & Overlays 2001 November - Disc 1.iso
/
dist
/
roboinst.idb
/
usr
/
etc
/
roboinst.z
/
roboinst
Wrap
Text File
|
2001-10-10
|
15KB
|
675 lines
#! /usr/bin/perl
#Tag 0x00000f00
#ident "$Revision $"
# Copyright 1997-2000, Silicon Graphics, Inc.
# All Rights Reserved.
#
# This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
# the contents of this file may not be disclosed to third parties, copied or
# duplicated in any form, in whole or in part, without the prior written
# permission of Silicon Graphics, Inc.
#
# RESTRICTED RIGHTS LEGEND:
# Use, duplication or disclosure by the Government is subject to restrictions
# as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
# and Computer Software clause at DFARS 252.227-7013, and/or in similar or
# successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
# rights reserved under the Copyright Laws of the United States.
# roboinst
#
# starts the automatic installation process on each of the hosts listed on
# the command line. If no host is specified, automatic installation is
# started on the current host.
# Initialization
$TMPDIR = $ENV{'TMPDIR'} || '/usr/tmp';
$ENV{'PATH'} = "/sbin:/usr/bin:/usr/bsd:/usr/sbin:/etc:/usr/etc:";
@dirs = split(/\//,$0);
$O = "$dirs[$#dirs]";
$VERSION = "1";
$CONFIGARGS = "/etc/config/roboinst.options";
$GETHOSTBYNAME = "/usr/etc/gethostbyname";
$ROBOSTART = "/usr/etc/roboinst_start";
$ID = "/usr/bin/id";
$CONFIGDEF = "/usr/local/boot/roboinst/custom/";
$SPOOLDIR = "/var/adm/roboinst";
$HOSTFILE = "$SPOOLDIR/hosts.dat";
$RSH = "/usr/bsd/rsh";
$HOSTCHK = "/usr/etc/roboinst_check";
if (open(ARGS,"<$CONFIGARGS")) {
$_ = <ARGS>;
close(ARGS);
@ARGV = (split, @ARGV);
}
$HOSTMAX = -1;
$HOSTCNT = 0;
$HOSTERR = "";
# parse command line
$usage =
"usage: ${O} [ -Llmnqrs ] [ -P disk ] [ -b bootdir ] [ -c configdir ]\n\t\t[ -f distribution ] [ -F selectionsfile ] [ -t time ] [ -N mode ] host ...\n";
require 'getopts.pl'; # fancy option parsing
if (! &Getopts('b:c:df:F:g:lLm:nN:pP:qrs:t:y')) {
die $usage;
}
if (defined $opt_s) {
$RSH = $opt_s;
}
if (defined $opt_l) {
&list_output();
exit(0);
}
if (defined $opt_q) {
&list_queue();
exit(0);
}
if (defined $opt_r) {
&job_remove();
exit(0);
}
# beginning of normal processing
unless (defined $opt_b || defined $opt_L) {
die $usage;
}
unless (defined $opt_n || defined $opt_y || defined $opt_t) {
warn "${O}: no time specified, running in test mode (-n)\n";
print STDERR "${O}: specify -y to override test mode\n";
}
# set up arguments for remote roboinst_start command
if (defined $opt_t) {
if ($opt_t eq "now") { # if time is now...
$timestr = "";
} else { # otherwise...
$timestr = "-t \"$opt_t\"";
}
$yesnostr = (defined $opt_n ? "-n" : "-y"); # queue it!
} else {
$timestr = "";
$yesnostr = (defined $opt_y ? "-y" : "-n");
}
$debugstr = (defined $opt_d ? "-d" : "");
if (defined $opt_P) {
if ($opt_P =~ /[()]/) {
$partitionstr = "-P \"$opt_P\"";
} else {
$partitionstr = "-P $opt_P";
}
} elsif (defined $opt_p) {
$partitionstr = "-p";
}
$gracestr = (defined $opt_g ? "-g$opt_g" : "");
chop($Hostname = `hostname`);
$Hostip = &getipaddr($Hostname);
chop($Cwd = `pwd`);
$livestr = "";
if (defined $opt_L) {
$livestr = "-L";
$timestr = "-t now" unless $timestr; # make sure job gets submitted
$bootstr = "";
} elsif (defined $opt_b) {
($bootserver,$bootdir) = &configdir_parse($opt_b);
unless ($bootdir) {
die "${O}: directory not specified in -b $opt_b\n";
}
if (! $bootserver) {
$bootserver = $Hostname; # default to localhost
}
$bootdir = "${bootserver}:$bootdir";
$bootstr = "-b $bootdir";
}
($configserver,$configdir) = &configdir_parse($opt_c);
unless ($configdir) {
$configdir = $CONFIGDEF;
}
if ($configserver) {
$configip = &getipaddr($configserver);
} else {
$configserver = $Hostname;
$configip = $Hostip; # default to localhost
}
if (defined $opt_N) {
if ($opt_N !~ /local|none|bootp|1533|dhcp/i) {
die "usage: -N [dhcp|bootp1533|local]";
}
print STDERR "using \U$opt_N\E for ip address and network info\n"
if ($opt_d);
$netmodestr = "-N $opt_N";
} else {
$netmodestr = "";
}
$configstr = "-c ${configip}:$configdir";
if (defined $opt_f) {
($instserver,$instdir) = &configdir_parse($opt_f);
unless ($instdir) {
die "${O}: directory not specified in -f $opt_f\n";
}
$instuser = "";
if ($instserver) {
if ($instserver =~ m/^(.+@)(.+)$/) { # see if user@host
$instuser = $1; # user@
$instserver = $2; # host
}
$instip = &getipaddr($instserver);
} else {
$instip = $Hostip;
}
if ($instip eq $Hostip) {
unless (-r $instdir) {
die "${O}: distribution does not exist (-f $instdir)\n";
} elsif (substr($instdir,0,1) ne "/") {
$instdir = "$Cwd/$instdir";
}
}
$instargs = "-I default -f $instuser${instip}:$instdir ";
print STDERR "${O}: inst -a $instargs\n"
if (defined $opt_d);
}
if (defined $opt_F) {
($instserver,$instdir) = &configdir_parse($opt_F);
unless ($instdir) {
die "${O}: filename not specified in -F $opt_F\n";
}
$instuser = "";
if ($instserver) {
if ($instserver =~ m/^(.+@)(.+)$/) { # see if user@host
$instuser = $1; # user@
$instserver = $2; # host
}
$instip = &getipaddr($instserver);
} else {
$instip = $Hostip;
}
if ($instip eq $Hostip) {
unless (-r $instdir) {
die "${O}: selections file does not exist (-F $instdir)\n";
} elsif (substr($instdir,0,1) ne "/") {
$instdir = "$Cwd/$instdir";
}
}
$instargs .= "-F $instuser${instip}:$instdir ";
print STDERR "${O}: inst -a $instargs\n"
if (defined $opt_d);
}
$emailstr = "";
if (defined $opt_m) {
$emailstr = "-m $opt_m";
}
if (defined $instargs) {
$instcmd = "inst -a ";
if ($yesnostr ne "-y") {
$instcmd .= "-n ";
}
$instcmd .= $instargs;
}
$roboinst_command =
"$ROBOSTART -z $yesnostr $debugstr $gracestr $livestr $netmodestr $partitionstr $bootstr $configstr $timestr $emailstr";
# If we are passing any of the new options (-N, -e), test also to see if a
# current version of roboinst_start is installed.
if ($netmodestr || $emailstr) {
$teststr = "test -x $ROBOSTART && $ROBOSTART -V 1.1 >/dev/null 2>&1";
} else {
$teststr = "test -x $ROBOSTART";
}
if ($instcmd) {
$roboinst_command =
"/bin/sh -c 'if ( $teststr ) || $instcmd ; then $roboinst_command ; else echo roboinst install failed ; fi'";
} else {
$roboinst_command =
"/bin/sh -c 'if $teststr ; then $roboinst_command; else echo \"roboinst not installed, use -f to specify installation directory\"; fi'";
}
print STDERR $roboinst_command,"\n"
if (defined $opt_d);
if ($#ARGV == -1) {
if ($> != 0) {
die "${0}: Must be root to start installation\n";
}
chop($host = `hostname`);
&job_submit($host,($roboinst_command));
}
while ($#ARGV >= 0) {
$host = $ARGV[0];
shift @ARGV;
@command = ($RSH, $host, "-l", "root", "-n", $roboinst_command);
&job_submit($host,@command);
}
exit(0); # success?
#
# ---- end of main processing ----
#
# getipaddr - return the IP address for a given host ($1)
sub getipaddr {
local($hostname) = @_;
if (! -x $GETHOSTBYNAME) {
die "${O}: $GETHOSTBYNAME not installed, aborting\n";
}
local($addr) = `$GETHOSTBYNAME $hostname | \
nawk -v a=0 '/^$hostname / { a=\$3; exit }
END { print a }'`;
chop $addr;
die "${O}: unable to convert $hostname to an IP address\n"
if ($addr eq "0");
return $addr;
}
# result_print
#
# display result of remote command
sub result_print {
local($host,$message) = @_;
local(@lines) = split(/\n/,$message);
foreach (@lines) {
print "${host}: $_\n";
}
}
# result_save
#
# remember job number for possible remove (-r)
sub result_save {
local($host,$message) = @_;
local(@lines) = split(/\n/,$message);
foreach (@lines) {
if (m/job \S+ at/) {
local($jobinfo) = "${host}: $_";
&job_save($host,$jobinfo);
last;
}
}
}
# job_save
#
# save job number to file, by ip address
sub job_save {
local($hostname,$jobnum) = @_;
if (! -d $SPOOLDIR) {
$result = `mkdir -p $SPOOLDIR 2>&1`;
if (! -d $SPOOLDIR) {
&result_print("${O}",$result);
return;
}
}
local($hostip) = &getipaddr($hostname);
if (open(SPOOL,">$SPOOLDIR/$hostip")) {
print SPOOL $jobnum,"\n";
close(SPOOL);
} else {
warn "${O}: unable to write queue file $SPOOLDIR/$hostip\n";
}
}
# job_read
#
# get job number from file, by ip address
sub job_read {
local($hostname) = @_;
if (! -d $SPOOLDIR) {
warn "${O}: no queue directory $SPOOLDIR, job number not available\n";
return "";
}
local($hostip) = &getipaddr($hostname);
if (open(SPOOL,"<$SPOOLDIR/$hostip")) {
local($line) = <SPOOL>;
close(SPOOL);
if ($line =~ m/job \S+ at/) {
return $line;
}
warn "${O}: invalid queue file $SPOOLDIR/$hostip, job number not available\n";
} else {
warn "${O}: no queue file $SPOOLDIR/$hostip for $host\n";
}
return "";
}
# job_clear
#
# clear job number file (ip address)
sub job_clear {
local($hostname) = @_;
return unless (-d $SPOOLDIR);
local($hostip) = &getipaddr($hostname);
unlink "$SPOOLDIR/$hostip";
}
# list_queue
#
# list the jobs in the queue directory
sub list_queue {
opendir(DIR,$SPOOLDIR) ||
die "${O}: no queue directory $SPOOLDIR\n";
local(@files);
local($file);
while (defined ($file = readdir(DIR))) {
print STDERR $file,"\n" if ($opt_d);
next if ($file eq "." || $file eq "..");
push(@files,$file);
}
close(DIR);
foreach $file (sort @files) {
if (open(SPOOL,"<$SPOOLDIR/$file")) {
print $_ while (<SPOOL>);
close(SPOOL);
}
}
}
# configdir_parse
#
# parse configdir string
sub configdir_parse {
local($str) = @_;
local($hostname,$path);
if ($str =~ m/^(\S*):(\S*)$/i) {
$hostname = $1;
$path = $2;
} else {
$hostname = "";
$path = $str;
}
return ($hostname,$path);
}
# list output from host
sub list_output {
local($exp) = "";
while ($#ARGV >= 0) {
$host = $ARGV[0];
shift @ARGV;
if ($exp ne "") {
$exp .= "|";
}
$exp .= $host;
}
open(LOG,"</var/adm/SYSLOG") ||
die "${O}: unable to read /var/adm/SYSLOG\n";
while (<LOG>) {
if (m/^\S+\s+\S+\s+\S+\s+[0-9][A-Z]:($exp)/o) {
print $_;
}
}
close(LOG);
}
# remove (cancel) job
sub job_remove {
while ($#ARGV >= 0) {
$host = $ARGV[0];
shift @ARGV;
local($jobinfo) = &job_read($host);
next unless ($jobinfo =~ m/job (\S+) at/);
local($jobnum) = $1;
print "${O}: cancelling job $jobnum on $host\n";
$result = `$RSH $host -l root at -r $jobnum 2>&1`;
&result_print($host,$result);
if ($result eq "") {
&job_clear($host);
}
}
}
# check given hostname to make sure it isn't a required server
sub is_server {
local($hostname) = @_;
local($hostip) = &getipaddr($hostname);
local($bootip) = &getipaddr($bootserver);
if ($hostip eq $bootip) {
warn "${O}: cannot install on bootserver ($bootserver)\n";
return 1;
}
if ($hostip eq $configip) {
warn "${O}: cannot install on configserver ($configserver)\n";
return 1;
}
return 0;
}
# submit job
sub job_submit {
local($hostname,@cmd) = @_;
local($pid);
# do not submit job if this is a server machine (unless we're live)
return unless ($opt_L || ! &is_server($hostname));
print "${O}: submitting job on $hostname\n";
if (($pid = open(JOB, "-|")) == 0) {
exec @cmd;
} elsif ($pid > 0) {
local($result) = "";
while (<JOB>) {
if (m/roboinst: PROMIFADDR -z (.*)/) {
local($chaddr) = $1;
print STDERR "${O}: $hostname has hardware address $chaddr\n"
if ($opt_d);
&host_check($hostname,$chaddr);
next; # do not echo this return code
}
$result .= $_;
&result_print($hostname,$_);
}
close(JOB);
&result_save($hostname,$result);
} else {
print "${O}: unable to submit job on ${hostname}\: $!\n";
}
}
# host_check
sub host_check {
local($hostname,$chaddr) = @_;
print STDERR "${O}: looking up $hostname ($chaddr)\n"
if ($opt_d);
if (! -d $SPOOLDIR) {
$result = `mkdir -p $SPOOLDIR 2>&1`;
if (! -d $SPOOLDIR) {
&result_print("${O}",$result);
}
}
local($newfile) = "$HOSTFILE\.new";
local($output) = 0;
if (open(NADDRS,">$newfile")) {
$output = 1;
}
local($found) = 0;
local($count) = 0;
if (open(ADDRS,"<$HOSTFILE")) {
while (<ADDRS>) {
chop;
next unless m/(\S+)\s(\S+)$/;
$count++;
if ($1 eq $chaddr) {
$found = $count;
print NADDRS "$1 $hostname\n" if ($output);
} else {
print NADDRS "$1 $2\n" if ($output);
}
}
close(ADDRS);
}
if ($found == 0) {
print NADDRS "$chaddr $hostname\n" if ($output);
$found = ++$count;
}
if ($output) {
close(NADDRS);
rename($newfile,$HOSTFILE);
}
local($count) = $found;
if ($HOSTMAX >= 0 && $count > $HOSTMAX) {
&license_error();
} elsif ($count > $HOSTCNT) {
if (-x $HOSTCHK) {
$HOSTERR = `$HOSTCHK $count 2>&1`;
local(@lines) = split(/\n/,$HOSTERR);
$HOSTERR = "";
local($retcnt) = 0;
foreach (@lines) {
if (m/^roboinst: HOSTCNT (\d+)$/) {
$retcnt = int($1);
} else {
$HOSTERR .= $_;
}
}
if ($retcnt > $HOSTCNT) {
$HOSTCNT = $retcnt;
}
if ($? && 0xFF) {
&license_error();
}
} else {
$HOSTERR = "";
$HOSTCNT = 0;
}
if ($HOSTCNT < $count) {
$HOSTMAX = $HOSTCNT;
&license_error();
}
}
}
sub license_error {
local($i) = $HOSTMAX;
if ($i == 0) {
print STDERR "Error: no licenses available for roboinst.\n";
} elsif ($i == 1) {
print STDERR "Error: only 1 license available for roboinst.\n";
} else {
print STDERR "Error: only $i licenses available for roboinst.\n";
}
if ($HOSTERR) {
print STDERR $HOSTERR;
}
print <<EOF
This product requires a license password, to obtain an Evaluation
or Permanent license please visit our license request web page:
http://www.sgi.com/Products/license.html
or send a blank email message to:
license\@sgi.com
In North America, Silicon Graphics' customers may request
Permanent licenses by sending a facsimile to:
(650) 390-0537
or by calling our technical support hotline
1-800-800-4SGI
If you are outside of North America or you are not a Silicon
Graphics support customer then contact your local support provider.
Note: Permanent Licenses require verification of entitlement
(i.e., Proof-of-Purchase).
EOF
}